from microbit import i2c
import gc

cmd = [
  [0xAE],
  [0xA4],
  [0xD5, 0xF0],
  [0xA8, 0x3F],
  [0xD3, 0x00],
  [0 | 0x0],
  [0x8D, 0x14],
  [0x20, 0x00],
  [0x21, 0, 127],
  [0x22, 0, 63],
  [0xa0 | 0x1],
  [0xc8],
  [0xDA, 0x12],
  [0x81, 0xCF],
  [0xd9, 0xF1],
  [0xDB, 0x40],
  [0xA6],
  [0xd6, 0],
  [0xaf]
]

# ' ' - '~' 0x20 - 0x7F
Font_5x7 = bytes(b'\
\x00\x00\x00\x00\x00\
\x00\x00\x5F\x00\x00\
\x00\x07\x00\x07\x00\
\x14\x7F\x14\x7F\x14\
\x24\x2A\x07\x2A\x12\
\x23\x13\x08\x64\x62\
\x37\x49\x55\x22\x50\
\x00\x05\x03\x00\x00\
\x00\x1C\x22\x41\x00\
\x00\x41\x22\x1C\x00\
\x08\x2A\x1C\x2A\x08\
\x08\x08\x3E\x08\x08\
\x00\x50\x30\x00\x00\
\x08\x08\x08\x08\x08\
\x00\x60\x60\x00\x00\
\x20\x10\x08\x04\x02\
\x3E\x51\x49\x45\x3E\
\x00\x42\x7F\x40\x00\
\x42\x61\x51\x49\x46\
\x21\x41\x45\x4B\x31\
\x18\x14\x12\x7F\x10\
\x27\x45\x45\x45\x39\
\x3C\x4A\x49\x49\x30\
\x01\x71\x09\x05\x03\
\x36\x49\x49\x49\x36\
\x06\x49\x49\x29\x1E\
\x00\x36\x36\x00\x00\
\x00\x56\x36\x00\x00\
\x00\x08\x14\x22\x41\
\x14\x14\x14\x14\x14\
\x41\x22\x14\x08\x00\
\x02\x01\x51\x09\x06\
\x32\x49\x79\x41\x3E\
\x7E\x11\x11\x11\x7E\
\x7F\x49\x49\x49\x36\
\x3E\x41\x41\x41\x22\
\x7F\x41\x41\x22\x1C\
\x7F\x49\x49\x49\x41\
\x7F\x09\x09\x01\x01\
\x3E\x41\x41\x51\x32\
\x7F\x08\x08\x08\x7F\
\x00\x41\x7F\x41\x00\
\x20\x40\x41\x3F\x01\
\x7F\x08\x14\x22\x41\
\x7F\x40\x40\x40\x40\
\x7F\x02\x04\x02\x7F\
\x7F\x04\x08\x10\x7F\
\x3E\x41\x41\x41\x3E\
\x7F\x09\x09\x09\x06\
\x3E\x41\x51\x21\x5E\
\x7F\x09\x19\x29\x46\
\x46\x49\x49\x49\x31\
\x01\x01\x7F\x01\x01\
\x3F\x40\x40\x40\x3F\
\x1F\x20\x40\x20\x1F\
\x7F\x20\x18\x20\x7F\
\x63\x14\x08\x14\x63\
\x03\x04\x78\x04\x03\
\x61\x51\x49\x45\x43\
\x00\x00\x7F\x41\x41\
\x02\x04\x08\x10\x20\
\x41\x41\x7F\x00\x00\
\x04\x02\x01\x02\x04\
\x40\x40\x40\x40\x40\
\x00\x01\x02\x04\x00\
\x20\x54\x54\x54\x78\
\x7F\x48\x44\x44\x38\
\x38\x44\x44\x44\x20\
\x38\x44\x44\x48\x7F\
\x38\x54\x54\x54\x18\
\x08\x7E\x09\x01\x02\
\x08\x14\x54\x54\x3C\
\x7F\x08\x04\x04\x78\
\x00\x44\x7D\x40\x00\
\x20\x40\x44\x3D\x00\
\x00\x7F\x10\x28\x44\
\x00\x41\x7F\x40\x00\
\x7C\x04\x18\x04\x78\
\x7C\x08\x04\x04\x78\
\x38\x44\x44\x44\x38\
\x7C\x14\x14\x14\x08\
\x08\x14\x14\x18\x7C\
\x7C\x08\x04\x04\x08\
\x48\x54\x54\x54\x20\
\x04\x3F\x44\x40\x20\
\x3C\x40\x40\x20\x7C\
\x1C\x20\x40\x20\x1C\
\x3C\x40\x30\x40\x3C\
\x44\x28\x10\x28\x44\
\x0C\x50\x50\x50\x3C\
\x44\x64\x54\x4C\x44\
\x00\x08\x36\x41\x00\
\x00\x00\x7F\x00\x00\
\x00\x41\x36\x08\x00\
\x02\x01\x02\x04\x02\
')

ADDR = 0x3C
gc.collect()
screen = bytearray(1025)
screen[0] = 0x40

class OLED12864_I2C_6x8():
  def __init__(self):
    self.x = 0
    self.y = 0
    for c in cmd:
      self.command(c)

  def command(self, c):
    i2c.write(ADDR, b'\x00' + bytearray(c)) 

  def set_pos(self, col=0, page=0):
    self.command([0xb0 | page])
    c1, c2 = col & 0x0F, col >> 4
    self.command([0x00 | c1])
    self.command([0x10 | c2]) 

  def pixel(self, x, y, color=1):
    page, shift_page = divmod(y, 8)
    ind = x + page * 128 + 1
    b = screen[ind] | (1 << shift_page) if color else screen[ind] & ~ (1 << shift_page)
    screen[ind] = b
    self.set_pos(x, page)
    i2c.write(ADDR, bytearray([0x40, b]))

  def invert(self, v=1):
    n = 0xa7 if v else 0xa6
    self.command([n])

  def on(self):
    self.command([0xAF])

  def off(self):
    self.command([0xAE])

  def clear(self, c=0):
    global screen
    for i in range(1, 1025):
      screen[i] = 0
    self.draw()

  def draw(self):
    self.set_pos()
    i2c.write(ADDR, screen) 

  def char(self, ch, x=0, y=0, c=1):
    ind = x + y * 128 + 1
    n = (min(127, max(ord(ch), 32)) -32)*5
    for i in range(5):
      screen[ind+i] = Font_5x7[n+i] if c else Font_5x7[n+i]^0xFF
    screen[ind+5] = 0 if c else 0xFF
    self.set_pos(x, y)
    i2c.write(ADDR, b'\x40' + screen[ind:ind + 6])

  def print(self, s, c=1, newline=1):
    x, y = self.x, self.y
    for i in range(len(s)):
      self.char(s[i], x, y, c)
      x += 6
      if x > 125:
        x = 0; y = (y+1)%8
    if newline:
      x = 0; y = (y+1)%8
    self.x, self.y = x, y

